﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Health;
using SDS.SPHealthAnalyzerRules.Delegation.Helpers;

namespace SDS.SPHealthAnalyzerRules.Delegation.Rules
{
    /// <summary>
    /// Validates that the C2WTS is not running as a local account
    /// </summary>
    public class C2WTS_NotUsing_LocalAccount : SPHealthAnalysisRule
    {
        private Guid CorrelationToken = Guid.NewGuid();

        readonly private List<string> Errors = new List<string>();
        readonly private List<string> Remedies = new List<string>();

        public override SPHealthCategory Category { get { return SPHealthCategory.Configuration; } }
        public override SPHealthCheckErrorLevel ErrorLevel { get { return SPHealthCheckErrorLevel.Error; } }

        public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters
        {
            get
            {
                return new SPHealthAnalysisRuleAutomaticExecutionParameters()
                {
                    Schedule = SPHealthCheckSchedule.Daily,
                    Scope = SPHealthCheckScope.Any,
                    ServiceType = SPFarm.Local.Services.First(s => s.Name == "c2wts").GetType(),     // run on any server running C2WTS
                    RepairAutomatically = false
                };
            }
        }

        public override SPHealthCheckStatus Check()
        {
            // return variable, defualt value
            SPHealthCheckStatus outval = SPHealthCheckStatus.Failed;

            // log
            LoggingService.Write(LoggingService.Category_C2WTS, TraceSeverity.Verbose, "Executing Health Check", CorrelationToken);

            // running as the system account
            Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(delegate { doCheck(); });

            // set return value
            outval = Errors.Count == 0
                 ? SPHealthCheckStatus.Passed
                 : SPHealthCheckStatus.Failed;

            // log
            LoggingService.Write(
                LoggingService.Category_C2WTS,
                TraceSeverity.Verbose,
                String.Format("Health Check completed with outcome {0}", outval.ToString()),
                CorrelationToken);

            return outval;
        }

        public override string Summary { get { return "DELEGATION: Claims to Windows Token Service is running as a local account"; } }
        public override string Explanation
        {
            get {
                var x = Errors.Select(e => String.Format(@"- {0}", e))
                              .ToArray();
                return String.Format(
                    @"{0}The Claims to Windows Token Service (C2WTS) requires domain privileges which cannot be provided to local accounts." +
                    @"{0}" +
                    @"{0}The following errors were found:" +
                    @"{0}{1}",
                    
                    Environment.NewLine,
                    String.Join(Environment.NewLine, x)
                    ).Trim();
            }
        }
        public override string Remedy
        {
            get { return String.Format("Configure the Claims to Windows Token Service to use a dedicated domain account"); }
        }



        private void doCheck()
        {
            try
            {
                string SvcRunsAs_Raw = Helpers.Win32API.SvcConfigMgr.GetServiceAccount_W2CTS();

                // if running as local system, ignore... local system is an informational notice (another rule), not an error.
                if (SvcRunsAs_Raw.ToLower() == "LocalSystem".ToLower())
                    return;

                // validate that account is a domain account
                string SvcRunsAs_Domain = SvcRunsAs_Raw.Split('\\').First();
                //string SvcRunsAs_Name = SvcRunsAs_Raw.Split('\\').Last();
                if (SvcRunsAs_Domain.ToLower() == SPServer.Local.Name.ToLower())
                {
                    Errors.Add(String.Format(
                        @"{0}C2WTS is running as the LOCAL account [{1}]" +
                        @"{0}",
                        Environment.NewLine,
                        SvcRunsAs_Raw
                        ).Trim());
                }


            } // try
            catch (Exception ex)
            {
                LoggingService.Write(
                    LoggingService.Category_C2WTS,
                    TraceSeverity.High,
                    String.Format("Health Check encountered the following exception: {0}", ex.Message),
                    CorrelationToken);
            }

        } // doCheck()

    } // class
} // namespace
